#include "fig_enemybullet_master.h"
#include "fig_bullet_manager.h"
#include "fig_enemy_manager.h"
#include "fig_player_craft.h"
#include "fig_craft.h"
#include "fig_bonepart.h"
#include "fig_sounds.h"

#include "math/facing.h"

#include "util/mmgr.h"		    // Needs to come in early
#include "util/common_macros.h"		// macros


FIGEnemyBulletMaster::FIGEnemyBulletMaster()
{
	//Type, int GroupCount, float BulletFrequency, float DelayAfterBulletGroup, bool IsPlayer);
	
	for(int i  = 0; i < (int)BULLET_TYPES_COUNT; i++)
	{
		AddToManager((BULLET_TYPES)i);
	}

	
}

void		FIGEnemyBulletMaster::AddToManager(BULLET_TYPES Type)
{
	FIGBulletManager*  pBulletManager = new FIGBulletManager(
		                                    (FIGBullet::BULLET_TYPES)((int)Type + (int)FIGBullet::BULLET_TYPE_ENEMY_START + 1)  ,
												1,
												0.0f,
												0.0f,
												false
												);

	m_BulletManagers[Type] = pBulletManager;
}

FIGEnemyBulletMaster::~FIGEnemyBulletMaster()
{
	for(int i = 0; i < (int)BULLET_TYPES_COUNT; i++)
	{
		FIGBulletManager* pBulletMananger = m_BulletManagers[i];
		UTIL_SAFE_DELETE(pBulletMananger);
	}
}

FIGEnemyBulletMaster&		FIGEnemyBulletMaster::Instance()
{
	static FIGEnemyBulletMaster Inst;
	return Inst;
}

	
void	FIGEnemyBulletMaster::Render(const math::Vec2& Offset,float Scale)
{
	for(int i = 0; i < (int)BULLET_TYPES_COUNT; i++)
	{
		FIGBulletManager* pBulletMananger = m_BulletManagers[i];
		pBulletMananger->Render(Offset,Scale);
	}
}

void	FIGEnemyBulletMaster::RenderDebug(const math::Vec2& Offset,float Scale)
{	
	for(int i = 0; i < (int)BULLET_TYPES_COUNT; i++)
	{
		FIGBulletManager* pBulletMananger = m_BulletManagers[i];
		pBulletMananger->RenderDebug(Offset,Scale);
	}
}

void	FIGEnemyBulletMaster::Tick(float dt)
{
	for(int i = 0; i < (int)BULLET_TYPES_COUNT; i++)
	{
		FIGBulletManager* pBulletMananger = m_BulletManagers[i];
		pBulletMananger->Tick(dt);

		for(int i = 0 ; i < pBulletMananger->GetCount(); i++)
		{
			FIGBullet* pBullet = pBulletMananger->GetBulletByIndex(i);
			if(pBullet->IsAlive() && 
				FIGPlayerCraft::Instance().CanHit()
				)
			{
				FIGPlayerCraft::Instance().HitTest(pBullet);
			}
		}

	}

	for(int i = (int) m_DelayShootInfos.size()-1; i >= 0 ; i--)
	{
		FIGEnemyBulletMaster::DelayShootInfo* pDelayShootInfo = m_DelayShootInfos[i];
		pDelayShootInfo->Delay -= dt;
		if( pDelayShootInfo->Delay <= 0)
		{
			if(pDelayShootInfo->pShooter && 
					(
					!pDelayShootInfo->pShooter->IsAlive() ||
					!pDelayShootInfo->pShooter->IsReadyToFire() 
					)
				)
			{
				// already dead	or unable to shoot			
			}
			else
			{
				InternalShoot(pDelayShootInfo);
				if(pDelayShootInfo->ShootBone)
				{
					float SDegree = pDelayShootInfo->Degree;
					if(pDelayShootInfo->bIsOppositeBone)
						SDegree += 180.0f;
					pDelayShootInfo->ShootBone->Shoot(SDegree);
				}
				
			}
			m_DelayShootInfos.erase(m_DelayShootInfos.begin()+i);
			m_OldDelayShootInfos.push_back(pDelayShootInfo);   			

		}
		else
		{
			if(pDelayShootInfo->pShooter && !pDelayShootInfo->pShooter->IsAlive())
			{
				// dead , delete
				m_DelayShootInfos.erase(m_DelayShootInfos.begin()+i);
				m_OldDelayShootInfos.push_back(pDelayShootInfo);
			}
		}
	}
}



void		FIGEnemyBulletMaster::Shoot(
												FIGLifeObj*							pShooter,
												const math::Vec2&					GunPos,
												FIGEnemyBulletMaster::BULLET_TYPES	Type,
												FIGBullet::SHOOT_STYLES				ShootStyle,
												float								Degree,
												float								Delay,
												bool								IsShootToPlayer,
												FIGBonePart* 						pShootBone,
												bool								bIsOppositeBone,
												FIGSounds::SOUND_NAMES				Sfx
												)
{

	FIGEnemyBulletMaster::DelayShootInfo *pDelayShootInfo = NULL;
	if(m_OldDelayShootInfos.size() == 0)
		pDelayShootInfo = new FIGEnemyBulletMaster::DelayShootInfo;
	else
	{
		pDelayShootInfo = m_OldDelayShootInfos[0];
		m_OldDelayShootInfos.erase(m_OldDelayShootInfos.begin());
	}


	pDelayShootInfo->pShooter = pShooter;
	pDelayShootInfo->GunPos = GunPos;
	pDelayShootInfo->Type = Type;
	pDelayShootInfo->ShootStyle = ShootStyle;
	pDelayShootInfo->Degree = Degree;
	pDelayShootInfo->Delay = Delay;
	pDelayShootInfo->IsShootToPlayer = IsShootToPlayer;	
	pDelayShootInfo->ShootBone = pShootBone;
	pDelayShootInfo->bIsOppositeBone = bIsOppositeBone;
	pDelayShootInfo->Sfx = Sfx;
	m_DelayShootInfos.push_back(pDelayShootInfo);
	
}

void		FIGEnemyBulletMaster::InternalShoot(DelayShootInfo* pShootInfo)
{
	FIGBulletManager* pBulletMananger = NULL;
	if((int)pShootInfo->Type< (int)BULLET_TYPES_COUNT)
		pBulletMananger = m_BulletManagers[pShootInfo->Type];
	
	if(pBulletMananger)
	{

		math::Vec2 TargetDir;
		math::Vec2 ShootPos = pShootInfo->pShooter->GetPos() + pShootInfo->GunPos;
		
		if(pShootInfo->ShootBone)
		{
			TargetDir = math::Facing::VectorFromAngle(pShootInfo->ShootBone->GetRotation() + 180.0f);
		}
		else if ( pShootInfo->IsShootToPlayer)
		{
			TargetDir = FIGPlayerCraft::Instance().GetPos() - ShootPos;
			TargetDir.Normalize();
		}
		else
		{
			TargetDir = math::Facing::VectorFromAngle(pShootInfo->Degree);
		}
		
		float Dist = 0;
		if(pShootInfo->ShootBone)
			Dist = pShootInfo->ShootBone->GetSize().y * 0.4f;

		pBulletMananger->ShootTick(	
									pShootInfo->pShooter,
									ShootPos + (TargetDir * Dist  ),
									100,
									TargetDir, 
									pShootInfo->ShootStyle,
									pShootInfo->Sfx
									);
	}
}
	
void		FIGEnemyBulletMaster::Clear()
{
	for( int i = (int)BULLET_TYPES_COUNT - 1; i >= 0; i--)
	{
		FIGBulletManager*  pObj = m_BulletManagers[i];
		pObj->Clear();
		//UTIL_SAFE_DELETE(pObj);
	}
	// manager shouldn't got deleted
	//m_BulletManagers.resize(0);

	for( int i = (int)m_DelayShootInfos.size() - 1; i >= 0; i--)
	{
		DelayShootInfo*  pObj = m_DelayShootInfos[i];
		UTIL_SAFE_DELETE(pObj);
	}
	m_DelayShootInfos.resize(0);
		
	
}

void		FIGEnemyBulletMaster::DieAll()
{
	for( int i = (int)BULLET_TYPES_COUNT - 1; i >= 0; i--)
	{
		FIGBulletManager*  pObj = m_BulletManagers[i];
		pObj->DieAll();
		
	}
}


	
